using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using Newtonsoft.Json;
using UnityEditor.Experimental.GraphView;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UIElements;
using XLFrame.NodeEditor.Extensions;
namespace XLFrame.NodeEditor
{
    /// <summary>
    /// 节点视图父类
    /// </summary>
    public abstract class NodeGraphViewBase : GraphView
    {
        // 继承自这个类的要实现的方法
        // public new class UxmlFactory : UxmlFactory<NodeGraphView, GraphView.UxmlTraits> { }

        #region 属性

        /// <summary>
        /// 节点树数据
        /// </summary>
        public NodeTreeDataBase NodeTreeDataBase
        {
            get => m_nodeTreeDataBase;
            set
            {
                if (value != null)
                {
                    m_nodeTreeDataBase = value;
                    ResetNodeView();
                }
            }
        }
        
        private NodeTreeDataBase m_nodeTreeDataBase;
        
        /// <summary>
        /// 撤销队列
        /// </summary>
        private LimitedStack<RecallOfData> m_undoQueue = new LimitedStack<RecallOfData>(15);

        /// <summary>
        /// 窗体鼠标位置
        /// </summary>
        public Vector2 WindowMousePosition { get; private set; }

        /// <summary>
        /// 鼠标在视图中的位置
        /// </summary>
        public Vector2 GraphMousePosition { get; private set; }

        /// <summary>
        /// 节点图中的鼠标位置
        /// </summary>
        public Vector2 GraphLocalMousePosition { get; private set; }

        /// <summary>
        /// 设置视图位置,支持节点坐标直接设置
        /// </summary>
        public Vector3 ViewPosition
        {
            get => contentViewContainer.transform.position;
            set =>
                contentViewContainer.transform.position = new Vector3(-value.x*contentViewContainer.transform.scale.x, 
                                                                      -value.y*contentViewContainer.transform.scale.y, 0);
        }

        /// <summary>
        /// 视图缩放
        /// </summary>
        public Vector2 ViewScale
        {
            get => contentViewContainer.transform.scale;
            set => contentViewContainer.transform.scale = value;
        }

        /// <summary>
        /// 数据是否更新true为有未保存的数据
        /// </summary>
        public bool IsDataUpdate { get; private set; }

        /// <summary>
        /// 显示默认的右键菜单即英文版剪切删除等
        /// </summary>
        protected bool ShowDefaultContextMenu { get; set;}

        /// <summary>
        /// 拉线指定类型条件
        /// </summary>
        private Dictionary<Type,List<Func<Port,Port,bool>>> m_findPortCondition = new Dictionary<Type, List<Func<Port, Port, bool>>>();

        /// <summary>
        /// 拉线默认额外条件
        /// </summary>
        private List<Func<Port, Port, bool>> m_findPortExtraCondition = new List<Func<Port, Port, bool>>();

        /// <summary>
        /// 节点视图字典包含所有的节点视图
        /// </summary>
        private Dictionary<string, NodeViewBase> m_nodeViewDic = new Dictionary<string, NodeViewBase>();

        /// <summary>
        /// 节点视图自定义右键菜单
        /// </summary>
        private SearchMenuWindowProvider m_searchMenuWindowProvider;

        #endregion

        #region 事件

        /// <summary>
        /// 当鼠标移动时
        /// </summary>
        public event UnityAction<Vector2> OnMouseMoveEvent;

        /// <summary>
        /// 当视图缩放时
        /// </summary>
        public event UnityAction<Vector2> OnViewScaleEvent;

        /// <summary>
        /// 当连线被删除时 用于同步数据
        /// </summary>
        public event UnityAction<EdgeLine> OnEdgeRemoveEvent;

        /// <summary>
        /// 当节点被删除时 用于同步数据
        /// </summary>
        public event UnityAction<NodeViewBase> OnNodeRemoveEvent;

        /// <summary>
        /// 当连线被创建时 用于同步数据
        /// </summary>
        public event UnityAction<List<EdgeLine>> OnEdgeCreateEvent;

        /// <summary>
        /// 当节点位置刷新时 用于同步数据
        /// </summary>
        public event UnityAction<List<Node>> OnNodePositionUpdateEvent;

        /// <summary>
        /// 当节点被选中时
        /// </summary>
        public event UnityAction<NodeViewBase> OnNodeSelectedEvent;

        /// <summary>
        /// 当数据更新时,用于判断是否有未保存的数据
        /// </summary>
        public event UnityAction OnDataUpdateEvent;

        /// <summary>
        /// 当时所有节点数据从存档加载完成时(节点图创建完成后)
        /// </summary>
        public event UnityAction OnDataLoadedEvent;

        #endregion

        #region 初始化

        public NodeGraphViewBase()
        {
            Insert(0, new GridBackground());
            this.AddManipulator(new ContentZoomer()
            {
                maxScale = 3f,
                minScale = 0.1f,
            });
            this.AddManipulator(new ContentDragger());
            this.AddManipulator(new SelectionDragger());
            this.AddManipulator(new RectangleSelector());

            // 加载样式
            var styleSheet = Resources.Load<StyleSheet>("GraphViewStyle");
            styleSheets.Add(styleSheet);

            // 右键菜单
            m_searchMenuWindowProvider = ScriptableObject.CreateInstance<SearchMenuWindowProvider>();
            m_searchMenuWindowProvider.OnSelectEntryHandler = OnMenuSelectEntry;

            // 连线规则 逻辑线特判
            AddFindPortExtraCondition((startPort,endPort) => endPort.portType != typeof(ExecutionLine));
            AddFindPortCondition<ExecutionLine>((startPort, endPort) => IsTypeCompatible<ExecutionLine>(endPort));

            // 整数类型 特判
            AddFindPortCondition<int>((startPort, endPort) => IsPortNumericTypeCompatible(startPort,endPort));
            AddFindPortCondition<long>((startPort, endPort) => IsPortNumericTypeCompatible(startPort,endPort));
            AddFindPortCondition<float>((startPort, endPort) => IsPortNumericFloatTypeCompatible(startPort,endPort));
            AddFindPortCondition<double>((startPort, endPort) => IsPortNumericFloatTypeCompatible(startPort,endPort));


            // 事件
            graphViewChanged += OnGraphViewChanged;
            viewTransformChanged += OnViewTransformChanged;
            this.RegisterCallback<MouseMoveEvent>(OnMouseMove);
            this.RegisterCallback<WheelEvent>(OnWheelEvent);
            OnDataUpdateEvent += NodeGraphViewBase_OnDataUpdate;
            OnEdgeCreateEvent += NodeGraphViewBase_OnEdgeCreate;
            OnDataLoadedEvent += NodeGraphViewBase_OnDataLoaded;
            OnEdgeRemoveEvent += NodeGraphViewBase_OnEdgeRemove;
            OnNodeRemoveEvent += NodeGraphViewBase_OnNodeRemove;
            OnNodePositionUpdateEvent += NodeGraphViewBase_OnNodePositionUpdate;
            // 复制相关事件
            serializeGraphElements += SerializeGraphElementsFun;
            canPasteSerializedData += CanPasteSerializedDataFun;
            unserializeAndPaste += UnSerializeAndPasteFun;
            // 撤回相关
            this.RegisterCallback<KeyDownEvent>(OnKeyDownEvent);

        }

        /// <summary>
        /// 初始设置
        /// </summary>
        public virtual void Init()
        {
            if (NodeTreeDataBase is null) return;
            AddUndo();
            contentViewContainer.transform.position = NodeTreeDataBase.GraphViewData.Position;
            contentViewContainer.transform.scale = NodeTreeDataBase.GraphViewData.Scale;
        }

        #endregion

        #region 事件处理

        #region 事件监听

        #region 序列化

        /// <summary>
        /// 反序列化字符串
        /// </summary>
        /// <param name="operationname"></param>
        /// <param name="data"></param>
        /// <exception cref="NotImplementedException"></exception>
        private void UnSerializeAndPasteFun(string operationname, string data)
        {
            // 是否为粘贴操作
            if(operationname != "Paste") return;
            
            // 替换GUID 使其不冲突
            data = ReplaceGUID(data);
            // Debug.Log(data);
            
            NodeSerializeData nodeDataBases = Json.DeserializeObject<NodeSerializeData>(data);
            List<NodeViewBase> viewBases = new List<NodeViewBase>(nodeDataBases.nodeDataBases.Count);

            
            // 计算偏移量
            // 找到左上角节点为基准
            Vector2 min = new Vector2(float.MaxValue,float.MaxValue);
            foreach (var item in nodeDataBases.nodeDataBases)
            {
                min.x = item.Position.x<min.x?item.Position.x:min.x;
                min.y = item.Position.y<min.y?item.Position.y:min.y;
            }
            var offset = GraphLocalMousePosition - min;
            
            // 恢复节点
            foreach (var item in nodeDataBases.nodeDataBases)
            {
                item.Position += offset;
                var node = RecoveryNode(item);
                RecoveryPort(node);
                RecoveryLogic(node);
                RecoveryStyle(node);
                viewBases.Add(node);
                
                // 添加数据
                NodeTreeDataBase.AddData(node.NodeData);

                // 设置选中状态
                selection.Add(node);
                node.selected = true;
            }
            
            // 这里需要先恢复节点,再恢复连线
            foreach (var item in viewBases)
            {
                RecoveryEdge(item);
            }
            
            // 这里需要恢复完成连线后调用,用于节点自定义的初始化事件
            foreach (var item in viewBases)
            {
                CallOnNodeDataLoadingDataEndEvent(item);
            }
            
            OnDataUpdateEvent?.Invoke();
        }

        /// <summary>
        /// 字符串是否可以反序列化
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        /// <exception cref="NotImplementedException"></exception>
        private bool CanPasteSerializedDataFun(string data)
        {
            NodeSerializeData nodeDataBases = Json.DeserializeObject<NodeSerializeData>(data);
            return nodeDataBases is not null;
        }

        /// <summary>
        /// 序列化图元
        /// </summary>
        /// <param name="elements"></param>
        /// <returns></returns>
        /// <exception cref="NotImplementedException"></exception>
        private string SerializeGraphElementsFun(IEnumerable<GraphElement> elements)
        {
            // 只有边两头都有连接才保存并序列化
            
            List<NodeDataBase> nodeDataBases = new List<NodeDataBase>();
            Dictionary<string,NodeDataBase> nodeDataBaseDic = new Dictionary<string, NodeDataBase>();
            
            foreach (var item in elements)
            {
                if(item is NodeViewBase node)
                {
                    nodeDataBases.Add(node.NodeData.Clone());
                }
            }

            // 移除外部连接逻辑
            foreach (var item in nodeDataBases)
            {
                nodeDataBaseDic.Add(item.GUID,item);
            }

            foreach (var item in nodeDataBases)
            {
                foreach (var nodePort in item.GetOutputPort())
                {
                    // 找到所有连接的输入节点不在 nodeDataBaseDic 字典中的连接关系
                   var nullLink = nodePort.NodeLinkDatas.Values.ToArray()
                                          .Where(t => !nodeDataBaseDic.ContainsKey(t.InputNodeGuid));
                   // 将这些连接关系从输出端口中移除
                   foreach (var link in nullLink)
                   {
                       nodePort.NodeLinkDatas.Remove(link.EdgeGuid);
                   }
                }
            }

            NodeSerializeData nodeSerializeData = new NodeSerializeData(nodeDataBases);
            string json = Json.SerializeObject(nodeSerializeData,Formatting.Indented);
            Debug.Log(json);
            return json;
        }

        /// <summary>
        /// 替换GUID
        /// </summary>
        /// <param name="json"></param>
        /// <returns></returns>
        private string ReplaceGUID(string json)
        {
            string pattern = @"[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}";
            MatchCollection matches = Regex.Matches(json, pattern);
            
            HashSet<string> uniqueGuids = new HashSet<string>();
            foreach (Match match in matches)
            {
                uniqueGuids.Add(match.Value);
            }
            
            StringBuilder sb = new StringBuilder(json);
            foreach (string guid in uniqueGuids)
            {
                string newGuid = Guid.NewGuid().ToString();
                sb.Replace(guid, newGuid);
            }

            return sb.ToString();
        }
        
        #endregion

        
        /// <summary>
        /// [注册在 OnNodePositionUpdateEvent]
        /// 节点位置更新
        /// </summary>
        /// <param name="arg0"></param>
        private void NodeGraphViewBase_OnNodePositionUpdate(List<Node> arg0)
        {
            foreach (var item in arg0)
            {
                if (item is NodeViewBase node)
                {
                    node.NodeData.Position = node.GetPosition().position;
                }
            }
            OnDataUpdateEvent?.Invoke();
        }

        /// <summary>
        /// [注册在 OnNodeRemoveEvent]
        /// 当节点被删除时
        /// </summary>
        /// <param name="arg0"></param>
        private void NodeGraphViewBase_OnNodeRemove(NodeViewBase arg0)
        {
            //Debug.Log("删除节点:" + arg0.title);
            NodeTreeDataBase.RemoveData(arg0.NodeData.GUID);
            OnDataUpdateEvent?.Invoke();
        }

        /// <summary>
        /// [注册在 OnEdgeRemoveEvent]
        /// 当连线被删除时
        /// </summary>
        /// <param name="arg0"></param>
        private void NodeGraphViewBase_OnEdgeRemove(EdgeLine arg0)
        {
            var output = arg0.output.node as NodeViewBase;
            var input = arg0.input.node as NodeViewBase;
            if(output is null || input is null) return;
            var outputPort = output.NodeData.GetOutputPort(arg0.output.name);
            outputPort.Remove(arg0.name);
            
            // 移除输入端口对输出端口对象的引用
            arg0.input.GetPortData().Value = null;            
            
            OnDataUpdateEvent?.Invoke();
        }

        /// <summary>
        /// [注册在 OnDataLoadedEvent]
        /// 节点数据完成复原后
        /// </summary>
        private void NodeGraphViewBase_OnDataLoaded()
        {
            OnDataLoad();
        }


        /// <summary>
        /// 当数据加载完成时(节点图创建完成后)
        /// </summary>
        protected virtual void OnDataLoad()
        {

        }

        /// <summary>
        /// [注册在 OnEdgeCreateEvent]
        /// 当连线被创建时
        /// </summary>
        /// <param name="arg0"></param>
        private void NodeGraphViewBase_OnEdgeCreate(List<EdgeLine> arg0)
        {
            // Debug.Log("创建链接");
            foreach (var item in arg0)
            {
                (item.input.node as NodeViewBase)?.ConnectEdgeEvent(item,true);
                (item.output.node as NodeViewBase)?.ConnectEdgeEvent(item,false);
            }
            OnDataUpdateEvent?.Invoke();
        }

        /// <summary>
        /// [注册在 OnDataUpdateEvent]
        /// 当数据更新时
        /// </summary>
        private void NodeGraphViewBase_OnDataUpdate()
        {
            IsDataUpdate = true;
            AddUndo();
        }

        /// <summary>
        /// 添加当前状态到撤回列表
        /// </summary>
        private void AddUndo()
        {
            // 缓存数据,实现撤销重做
            string json = Json.SerializeObject(NodeTreeDataBase);

            if (m_undoQueue.Count == 0)
            {
                m_undoQueue.Enqueue(new RecallOfData(json));
            }

            // m_undoQueue 数量不为0时
            if (m_undoQueue.Peek().Json == json)
                return;

            var data = new RecallOfData(json);
            // 如果两次操作时间间隔小于100ms,替换最后一个元素
            if (data.CreationTime - m_undoQueue.Peek().CreationTime <= 100)
                m_undoQueue.ReplaceLast(data);
            else
                m_undoQueue.Enqueue(data);

            // Debug.Log("添加撤回数据:"+m_undoQueue.Count);
        }
        
        /// <summary>
        /// [注册在 this.RegisterCallback KeyDownEvent]
        /// 监听按键事件
        /// </summary>
        /// <param name="evt"></param>
        private void OnKeyDownEvent(KeyDownEvent evt)
        {
            // Check if Ctrl+Z is pressed
            if (evt.ctrlKey && evt.keyCode == KeyCode.Z)
            {
                UndoLastAction();
                evt.StopPropagation(); // Stop the event from propagating further
            }
        }

        private void UndoLastAction()
        {
            var previousState = m_undoQueue.Count >= 2 ? m_undoQueue.Dequeue() : m_undoQueue.Peek();
            
            NodeTreeDataBase = Json.DeserializeObject<NodeTreeDataBase>(previousState.Json);
            DataUpdate();
            // Debug.Log("撤回按键,剩余数据"+m_undoQueue.Count);
        }
        
        /// <summary>
        /// [注册在 this.RegisterCallback WheelEvent]
        /// 当滚轮滚动时
        /// </summary>
        /// <param name="evt"></param>
        private void OnWheelEvent(WheelEvent evt)
        {
            OnViewScaleEvent?.Invoke(ViewScale);
        }

        /// <summary>
        /// [注册在 this.RegisterCallback MouseMoveEvent]
        /// 当鼠标移动时
        /// </summary>
        /// <param name="evt"></param>
        private void OnMouseMove(MouseMoveEvent evt)
        {
            // 更新MousePosition为鼠标当前位置
            GraphMousePosition = evt.localMousePosition;
            WindowMousePosition = evt.mousePosition;
            GraphLocalMousePosition = contentViewContainer.WorldToLocal(evt.mousePosition);
            OnMouseMoveEvent?.Invoke(evt.localMousePosition);
        }

        /// <summary>
        /// [注册在 viewTransformChanged]
        /// 视图变化事件
        /// </summary>
        /// <param name="graphView"></param>
        private void OnViewTransformChanged(GraphView graphView)
        {
            if (NodeTreeDataBase is null) return;
            NodeTreeDataBase.GraphViewData.Position = contentViewContainer.transform.position;
            NodeTreeDataBase.GraphViewData.Scale = contentViewContainer.transform.scale;
        }

        private List<Node> m_selectionhc = new List<Node>();
        
        /// <summary>
        /// [注册在 graphViewChanged]
        /// 节点变化事件
        /// </summary>
        /// <param name="graphViewChange"></param>
        /// <returns></returns>
        private GraphViewChange OnGraphViewChanged(GraphViewChange graphViewChange)
        {
            // 被删除的连线
            if (graphViewChange.elementsToRemove != null)
            {
                foreach (var item in graphViewChange.elementsToRemove)
                {
                    if (item is EdgeLine edge)
                    {
                        OnEdgeRemoveEvent?.Invoke(edge);
                    }
                    else if (item is NodeViewBase node)
                    {
                        OnNodeRemoveEvent?.Invoke(node);
                    }
                }
            }

            // 创建连线
            if (graphViewChange.edgesToCreate != null)
            {
                OnEdgeCreateEvent?.Invoke(graphViewChange.edgesToCreate.OfType<EdgeLine>().ToList());
            }

            // 被选中的节点,拖拽结束
            if (selection.Count != 0)
            {
                m_selectionhc.Clear();
                foreach (var item in selection)
                {
                    if (item is Node nodeView)
                    {
                        m_selectionhc.Add(nodeView);
                    }
                }
                OnNodePositionUpdateEvent?.Invoke(m_selectionhc);
            }

            return graphViewChange;
        }
        #endregion

        #region 连线规则

        public void RemoveEdge(EdgeLine edge)
        {
            OnEdgeRemoveEvent?.Invoke(edge);

            // 移除端口连接
            edge.input.Disconnect(edge);
            edge.output.Disconnect(edge);

            RemoveElement(edge);
        }

        /// <summary>
        /// 连线规则不能连接自己，不能连接相同方向的端口，只能连接相同类型的端口
        /// </summary>
        /// <param name="startPort"></param>
        /// <param name="nodeAdapter"></param>
        /// <returns></returns>
        public override List<Port> GetCompatiblePorts(Port startPort, NodeAdapter nodeAdapter)
        {
            // 这里的startPort是当前拖拽的端口
            // endPort是当前视图所有的端口

            // 判断特定类型的端口
            foreach (var item in m_findPortCondition)
            {
                if(startPort.portType == item.Key)
                {
                    return ports.ToList().Where(endPort =>
                        FindPortDefauftCondition(startPort, endPort) &&
                        m_findPortCondition[item.Key].All(x => x(startPort, endPort))
                    ).ToList();
                }
            }

            // 默认的连线规则
            return ports.ToList().Where(endPort =>
                FindPortDefauftCondition(startPort, endPort) &&
                IsEndPortTypeCompatible(startPort, endPort) &&
                m_findPortExtraCondition.All(x => x(startPort, endPort))
            ).ToList();
        }

        /// <summary>
        /// port 等于 T 类型
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="port"></param>
        /// <returns></returns>
        protected bool IsTypeCompatible<T>(Port port) 
        {
            return port.portType == typeof(T);
        }

        /// <summary>
        /// 添加连线查找特定端口的条件
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="condition"></param>
        protected void AddFindPortCondition<T>(Func<Port, Port, bool> condition)
        {
            var type = typeof(T);

            if (m_findPortCondition.ContainsKey(type))
                m_findPortCondition[type].Add(condition);
            else
                m_findPortCondition.Add(type, new List<Func<Port, Port, bool>>() { condition });
        }

        /// <summary>
        /// 添加连线默认端口的额外条件
        /// </summary>
        /// <param name="condition"></param>
        protected void AddFindPortExtraCondition(Func<Port, Port, bool> condition)
        {
            m_findPortExtraCondition.Add(condition);
        }

        /// <summary>
        /// 查找连线未特定处理端口默认条件
        /// </summary>
        /// <returns></returns>
        protected virtual bool FindPortDefauftCondition(Port startPort, Port endPort)
        {
            return endPort.direction != startPort.direction &&
                endPort.node != startPort.node;
        }

        /// <summary>
        /// 判断结束端口是否为开始端口的类型或者是其父类
        /// </summary>
        /// <param name="startPort"></param>
        /// <param name="endPort"></param>
        /// <returns></returns>
        protected virtual bool IsEndPortTypeCompatible(Port startPort, Port endPort)
        {
            return endPort.portType == startPort.portType || 
                endPort.portType.IsAssignableFrom(startPort.portType) || 
                (startPort.direction == Direction.Input && startPort.portType.IsAssignableFrom(endPort.portType));
        }

        /// <summary>
        /// port 可以被整数类型连接
        /// </summary>
        /// <param name="startPort"></param>
        /// <param name="port"></param>
        /// <returns></returns>
        protected bool IsPortNumericTypeCompatible(Port startPort, Port port)
        {
            if(startPort.direction == Direction.Output)
            {
                return IsTypeCompatible<int>(port) ||
                IsTypeCompatible<long>(port) ||
                IsTypeCompatible<float>(port) ||
                IsTypeCompatible<double>(port) ||
                IsTypeCompatible<object>(port);
            }
            else
            {
                // TODO 这里long 转int可能会溢出
                return IsTypeCompatible<int>(port) ||
                IsTypeCompatible<long>(port);
            }
        }

        /// <summary>
        /// port 浮点数连接类型
        /// </summary>
        /// <param name="startPort"></param>
        /// <param name="port"></param>
        /// <returns></returns>
        protected bool IsPortNumericFloatTypeCompatible(Port startPort, Port port)
        {
            if (startPort.direction == Direction.Input)
            {
                return IsTypeCompatible<int>(port) ||
                    IsTypeCompatible<long>(port) ||
                    IsTypeCompatible<float>(port) ||
                    IsTypeCompatible<double>(port);
            }
            else
            {
                return IsTypeCompatible<float>(port) ||
                    IsTypeCompatible<double>(port) ||
                    IsTypeCompatible<object>(port);
            }
        }


        #endregion

        #endregion

        #region 右键菜单

        /// <summary>
        /// 当右键菜单选择时
        /// </summary>
        /// <param name="type"></param>
        /// <param name="tport"></param>
        /// <param name="searchTreeEntry"></param>
        /// <param name="context"></param>
        /// <returns></returns>
        private bool OnMenuSelectEntry(Type type, Port tport, SearchTreeEntry searchTreeEntry, SearchWindowContext context)
        {
            if (type is null) return false;
            var node = CreateNode(type, GraphLocalMousePosition);
            // node要转接口改为通用创建 重要!!!!目前右键菜单只支持创建节点
            if (tport is not null)
            {
                // 创建连线
                var nodePort = node.ConnectRecommendedPort(tport, true);
            }
            return true;
        }

        /// <summary>
        /// 右键菜单
        /// </summary>
        /// <param name="evt"></param>
        public override void BuildContextualMenu(ContextualMenuPopulateEvent evt)
        {
            if(ShowDefaultContextMenu)
                base.BuildContextualMenu(evt);

            //var clickPosition = contentViewContainer.WorldToLocal(evt.mousePosition);
            var screenMousePosition = GUIUtility.GUIToScreenPoint(evt.mousePosition);
            evt.menu.AppendAction("创建节点", x => {
                ShowSearchMenu();
            });

        }

        /// <summary>
        /// 在鼠标位置显示搜索菜单
        /// </summary>
        public void ShowSearchMenu(Port port = null)
        {
            // 检查Event.current是否为null
            if (Event.current != null)
            {
                // 获取当前事件的鼠标位置
                Vector2 mousePosition = Event.current.mousePosition;
                // 将GUI坐标转换为屏幕坐标
                Vector2 screenMousePosition = GUIUtility.GUIToScreenPoint(mousePosition);

                GraphLocalMousePosition = contentViewContainer.WorldToLocal(mousePosition);

                // 打印鼠标的屏幕坐标
                m_searchMenuWindowProvider.Open(screenMousePosition, port);
            }
            else
            {
                var screenMousePosition = GUIUtility.GUIToScreenPoint(WindowMousePosition);
                m_searchMenuWindowProvider.Open(screenMousePosition, port);
            }
        }

        #endregion

        #region 节点处理相关

        /// <summary>
        /// 添加节点到视图中,并保存数据
        /// </summary>
        /// <param name="node"></param>
        /// <param name="position"></param>
        protected void AddNode(NodeViewBase node, Vector2 position = default)
        {
            AddNodeView(node, position);
            NodeTreeDataBase.AddData(node.NodeData);
            OnDataUpdateEvent?.Invoke();
        }

        /// <summary>
        /// 自动创建节点,添加到视图中
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="position"></param>
        /// <returns></returns>
        public T CreateNode<T>(Vector2 position = default) where T : NodeViewBase ,new()
        {
            T node = new T();
            CallCreateNode(node);
            AddNode(node, position);
            return node;
        }

        /// <summary>
        /// 自动创建节点,添加到视图中
        /// </summary>
        /// <param name="type"></param>
        /// <param name="position"></param>
        /// <returns></returns>
        protected NodeViewBase CreateNode(Type type, Vector2 position = default)
        {
            if (Activator.CreateInstance(type) is not NodeViewBase node) return null;
            CallCreateNode(node);
            AddNode(node, position);
            return node;
        }

        /// <summary>
        /// 下一帧执行
        /// </summary>
        /// <param name="node"></param>
        private void ScheduleDelayedAction(NodeViewBase node)
        {
            schedule.Execute(()=>CallOnNodeAddViewEvent(node)).StartingIn(1); // 延迟1帧执行
        }

        /// <summary>
        /// 添加节点到视图,但不保存数据
        /// </summary>
        /// <param name="node"></param>
        /// <param name="position"></param>
        private void AddNodeView(NodeViewBase node, Vector2 position = default)
        {
            node.SetPosition(new Rect(position, node.GetPosition().size));
            node.OnNodeSelectedEvent += t => OnNodeSelectedEvent?.Invoke(t);
            AddElement(node);
            node.NodeData.Position = position;

            ScheduleDelayedAction(node);
        }

        #endregion

        #region 读档相关


        /// <summary>
        /// 重置到存档当前数据,这就是数据解析器转为节点视图
        /// 需要优化,重置时,不移除未修改的数据,只添加更改的数据,如果仅坐标发生变化,找到对应变化的节点,只更新坐标
        /// </summary>
        public void ResetNodeView()
        {
            RemoveAllNode();
            
            var data = NodeTreeDataBase.NodeDataBaseDic;
            foreach (var item in data.Values)
            {
                var nodeViewBase = RecoveryNode(item);
                RecoveryPort(nodeViewBase);
                RecoveryLogic(nodeViewBase);
                RecoveryStyle(nodeViewBase);
            }

            // 这里需要先恢复节点,再恢复连线
            foreach (var item in m_nodeViewDic.Values)
            {
                RecoveryEdge(item);
            }

            OnDataLoadedEvent?.Invoke();
            
            // 这里需要恢复完成连线后调用,用于节点自定义的初始化事件
            foreach (var item in m_nodeViewDic.Values)
            {
                CallOnNodeDataLoadingDataEndEvent(item);
            }
        }

        private void RemoveAllNode()
        {
            // 首先移除所有的节点
            foreach (var item in m_nodeViewDic)
            {
                RemoveElement(item.Value);
                foreach (var OutputPort in item.Value.NodePort.OutputPort)
                {
                    foreach (var link in OutputPort.Value.connections)
                    {
                        RemoveElement(link);
                    }
                }
            }
            m_nodeViewDic.Clear();
        }
        
        /// <summary>
        /// 恢复逻辑
        /// </summary>
        /// <param name="nodeDataBase"></param>
        private void RecoveryLogic(NodeViewBase nodeDataBase)
        {
            foreach (var item in nodeDataBase.NodeData.NodeLogicData)
            {
                var type = Type.GetType(item);
                if (type is null) continue;
                var logic = Activator.CreateInstance(type) as INodeLogic;
                if (logic is null) continue;
                nodeDataBase.NodeLogic.AddNodeLogic(logic);
            }
        }

        /// <summary>
        /// 恢复样式
        /// </summary>
        /// <param name="nodeViewBase"></param>
        private void RecoveryStyle(NodeViewBase nodeViewBase)
        {
            var StyleTypeList = nodeViewBase.NodeData.NodeStyleDatas;
            
            foreach (var item in StyleTypeList)
            {
                var data = NodeStyleBase.CreateNodeStyle(item);
                if (data is null) continue;
                
                nodeViewBase.NodeStyle.AddNodeStyle(data);
            }
            
            // 样式的端口放入到指定样式中,并通知初始化OnNodeStyleInit
            foreach (var item in nodeViewBase.NodeData.GetInputPort())
            {
                var data = nodeViewBase.NodeStyle.GetNodeStyle(item.ContainerID);
                data?.Ports.Add(item.GUID,GetPortForNode(item));
            }

            foreach (var item in nodeViewBase.NodeData.GetOutputPort())
            {
                var data = nodeViewBase.NodeStyle.GetNodeStyle(item.ContainerID);
                data?.Ports.Add(item.GUID,GetPortForNode(item));
            }

            // 通知样式层初始化
            nodeViewBase.NodeStyle.CallNodeStyleInit();
            
            Port GetPortForNode(PortViewData protData)
            {
                Type type = Type.GetType(protData.PortType);
                var port = nodeViewBase.NodePort.CreatePortForNode(type, protData.PortName, protData.GUID,
                                                                   ((Direction)protData.PortDirection) == Direction.Input, 
                                                                   (Port.Capacity)protData.PortCapacity, 
                                                                   false,CID:protData.ContainerID,addContainer:false);
                return port;
            }
        }

        /// <summary>
        /// 恢复端口数据
        /// </summary>
        /// <param name="nodeViewBase"></param>
        private void RecoveryPort(NodeViewBase nodeViewBase)
        {
            var inputPort = nodeViewBase.NodeData.GetInputPort();
            foreach (var item in inputPort)
            {
                if(item.ContainerID == "Node")
                    GetPortForNode(item);
            }

            var outputPort = nodeViewBase.NodeData.GetOutputPort();

            foreach (var item in outputPort)
            {
                // 这里只复原当前节点的端口,样式内的端口,将数据给样式,让他们自己处理
                if(item.ContainerID == "Node")
                    GetPortForNode(item);
            }

            nodeViewBase.RefreshExpandedState();

            void GetPortForNode(PortViewData protData)
            {
                Type type = Type.GetType(protData.PortType);
                var port = nodeViewBase.NodePort.CreatePortForNode(type, protData.PortName, protData.GUID,
                   ((Direction)protData.PortDirection) == Direction.Input, (Port.Capacity)protData.PortCapacity, 
                   false,CID:protData.ContainerID);
            }
        }

        /// <summary>
        /// 恢复连线
        /// </summary>
        private void RecoveryEdge(NodeViewBase nodeViewBase)
        {
            // 获取所有的输出端口 里面记录了连接关系
            var data = nodeViewBase.NodeData.GetOutputPort();
            if(data is null) return;
            foreach (var item in data)
            {
                // 找到视图中的真实端口
                Port outputPort = nodeViewBase.NodePort.GetOutputPort(item.GUID);
                if(outputPort is null) continue;
                
                // 拿到当前节点所有连接关系
                foreach (var linkData in item.NodeLinkDatas)
                {
                    // 拿到对应的输入端口
                    var inputPort = m_nodeViewDic[linkData.Value.InputNodeGuid].NodePort.GetInputPort(linkData.Value.PortGuid);
                    if(inputPort is null) continue;
                    var edge = LinkNodes(outputPort, inputPort);
                    if(edge is null) continue;
                    edge.name = linkData.Key;
                }
            }
        }

        /// <summary>
        /// 连接两个端口
        /// </summary>
        /// <param name="outputPort"></param>
        /// <param name="inputPort"></param>
        private EdgeLine LinkNodes(Port outputPort, Port inputPort)
        {
            if(outputPort is null || inputPort is null) return null;
            if(outputPort == inputPort) return null;
            var edge = new EdgeLine
            {
                output = outputPort,
                input = inputPort
            };

            edge.input.Connect(edge);
            edge.output.Connect(edge);
            
            Add(edge);
            
            inputPort.GetPortData().Value = outputPort.GetPortData();
            return edge;
        }

        /// <summary>
        /// 恢复节点
        /// </summary>
        private NodeViewBase RecoveryNode(NodeDataBase nodeDataBase)
        {
            var node = NodeViewBase.CreateNode(nodeDataBase,this);
            if(node is null)
            {
                Debug.LogError($"未找到节点类型:{nodeDataBase.NodeType}");
                return null;
            }

            AddNodeView(node, nodeDataBase.Position);
            m_nodeViewDic.Add(node.NodeData.GUID, node);
            return node;
        }
        #endregion

        #region 其他工具
        
        
        private void CallOnNodeDataLoadingDataEndEvent(INodeViewFrame nodeViewFrame)=>nodeViewFrame.OnNodeDataLoadingDataEndEvent();
        private void CallOnNodeAddViewEvent(INodeViewFrame nodeViewFrame)=>nodeViewFrame.OnNodeAddViewEvent();
        private void CallCreateNode(INodeViewFrame nodeViewFrame)=>nodeViewFrame.CreateNode(this);
        
        /// <summary>
        /// 设置状态为数据已保存
        /// </summary>
        public void SetIsDataUpdateSave()
        {
            IsDataUpdate = false;
        }

        /// <summary>
        /// 添加一条连线到视图中并调用创建连线事件
        /// </summary>
        /// <param name="edge"></param>
        public void AddEdge(EdgeLine edge)
        {
            Add(edge);
            OnEdgeCreateEvent?.Invoke(new List<EdgeLine>() { edge });
        }

        /// <summary>
        /// 数据更新了,标记需要保存数据
        /// </summary>
        public void DataUpdate()
        {
            OnDataUpdateEvent?.Invoke();
        }


        /// <summary>
        /// 获取所有节点
        /// </summary>
        /// <returns></returns>
        public NodeViewBase[] GetAllNodes()
        {
            return m_nodeViewDic.Values.ToArray();
        }

        /// <summary>
        /// 返回指定类型所有节点
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public  List<T> GetTypeAllNodes<T>() where T : NodeViewBase
        {
            List<T> list = new List<T>();
            foreach (var item in m_nodeViewDic.Values)
            {
                if (item is T obj)
                {
                    list.Add(obj);
                }
            }

            return list;
        }

        /// <summary>
        /// 通过GUID获取已存在的节点
        /// </summary>
        /// <param name="Guid"></param>
        /// <returns></returns>
        public NodeViewBase GetNode(string Guid)
        {
            return m_nodeViewDic.GetValueOrDefault(Guid);
        }
        
        #endregion
    }
}